<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  
  <link rel="stylesheet" href="/public/asset/bootstrap.min.css">
  <link rel="stylesheet" href="/public/asset/bootstrap-icons-141.css">
  <link rel="stylesheet" href="/public/asset/style.css">
  
  <script src="/public/asset/jquery.min.js"></script>
  <script src="/public/asset/dayjs.min.js"></script>
  <script src="/public/asset/bootstrap.bundle.min.js"></script>
  <script src="/public/asset/util.js"></script>
  <script src="/public/asset/follow-islands.js"></script>
  
  <title>All Islands in iPelago</title>
</head>
<body>
  <div id="root" class="container" style="max-width: 900px; min-width: 400px;"></div>

<script>

const Loading = CreateLoading();
const Alerts = CreateAlerts();
const Logs = CreateLogs();

const UpdateBtn = cc('button');
const TitleArea = {
  view: () => m('div').addClass('d-flex justify-content-start align-items-end my-5').append([
    m('div').addClass('display-6').text('Follow Islands'),
    m(UpdateBtn).text('update all').attr({type:'button'})
      .addClass('btn btn-outline-secondary btn-sm ms-2').hide(),
    m('a').attr({href:'/public/home.html',title:'home'})
      .addClass('btn btn-outline-secondary btn-sm ms-2').append(
        m('i').addClass('bi bi-house-door')
    ),
  ]),
};

const SubmitBtn = cc('button');
const Addresses = cc('textarea');
const AddressesArea = cc('div', null, [
  m('p').text('请把小岛地址粘贴到下面的文本框中，一行一个地址。然后点击 Submit 按钮。'),
  m(Addresses).addClass('form-control').on('input', () => {
    const self = $(Addresses.id);
    self.css('height', self.prop('scrollHeight'));
  }),
  m('p').addClass('text-center my-3').append(
    m(SubmitBtn).text('Submit').attr({type:'button'}).addClass('btn btn-primary')
  ),
]);

const IslandList = cc('div');

IslandList.append = (islands) => {
  const islandPairs = pairs(islands); // 两个一行，为了方便先组对。
  islandPairs.forEach(pair => {
    const row = cc('div');
    $(IslandList.id).append(m(row).addClass('row my-3'));
    pair.forEach(island => {
      const item = IslandItem(island);
      $(row.id).append(m('div').addClass('col-md-6 my-1').append(m(item)));
      item.init();
    });
  });
};

$('#root').append([
  m(TitleArea),
  m(Alerts).addClass('my-3'),
  m(AddressesArea),
  m(Logs),
  m(Loading),
  m(IslandList).addClass('my-5'),
]);

init();

function init() {
  ajax({method:'GET',url:'/api/all-islands',alerts:Alerts},
      (islands) => {
        if (!islands || islands.length == 0) {
          Alerts.insert('info', '尚未订阅任何岛');
          return;
        }
        IslandList.append(islands);

        $(UpdateBtn.id).show().click(() => {
          $(IslandList.id).hide();
          updateIslands(islands);
          $(UpdateBtn.id).hide();
        });
      }, null, () => {
        $(Loading.id).hide();
      });

  $(SubmitBtn.id).click(() => {
    disable(SubmitBtn.id);

    const addresses = $(Addresses.id).val().split('\n')
      .map(item => item.trim())
      .filter(item => item.length > 0);

    followIslands(addresses);
    // 在 followIslands 之后如果有代码，会立即执行，不会等待 followIslands。
  });

  window.setTimeout(() => { $(Addresses.id).focus() }, 1000);
}

function pairs(items) {
  const itemPairs = [];
  items.forEach( (e,i) => {
    if (i%2==0) {
      itemPairs.push([e])
    } else {
      itemPairs[itemPairs.length-1].push(e)
    }
  });
  return itemPairs;
}

function itemID(id) {
  return `i${id}`;
}

function IslandItem(island) {
  let avatar = '/public/avatars/default.jpg';
  if (island.Avatar) {
    avatar = island.Avatar;
  }
  const islandPage = '/public/island.html?id='+island.ID;
  const datetime = dayjs.unix(island.Message.time).format('YYYY-MM-DD HH:mm:ss');
  const Alerts = CreateAlerts(); // TODO: 考虑删除Alerts
  const self = cc('div', itemID(island.ID))

  self.view = () => m('div').attr({id:self.raw_id}).addClass('card').append([
    m('div').addClass('card-body').append([
      m('ul').addClass('list-group list-group-flush').append([
        m('li').addClass('list-group-item d-flex justify-content-start align-items-start mb-1').append([
          m('a').addClass('AvatarLink').attr({href:islandPage}).append(
            m('img').addClass('Avatar').attr({src:avatar,alt:'avatar'})
          ),
          m('div').addClass('ms-3').append([
            m('p').addClass('CardTitle').append(
              m('a').text(island.Name).attr({href:islandPage})
                .addClass('text-decoration-none text-dark fw-bold')),
          ]),
        ]),
        m('li').addClass('list-group-item mb-1').append([
          m('div').addClass('Datetime small').append(
            m('span').addClass('text-muted').text(datetime)
          ),
          m('span').addClass('small').text(island.Message.body),
        ]),
      ]),
      m(Alerts), // TODO: 考虑删除Alerts
    ]),
  ]);

  self.init = () => {
    const cardTitle = $(self.id).find('.CardTitle');
    if (island.Email) {
      cardTitle.append([
        m('span').addClass('small text-muted text-break').text(` (${island.Email})`),
      ]);
    }
    if (island.Link) {
      cardTitle.append([
        m('br'),
        m('a').addClass('small').text(island.Link).attr({href:island.Link}),
      ]);
    }
    if (!island.Note) {
      island.Note = island.Address;
    }
    cardTitle.append([
      m('br'),
      m('span').addClass('small text-muted text-break').text(island.Note),
    ]);
    if (island.Status) {
      $(self.id).find('.Datetime').append([
        ' ',
        m('span').addClass('IslandStatus'),
      ]);
      changeStatus(`${self.id} .IslandStatus`, island.Status);
    }
  };

  return self;
}

async function updateIslands(islands) {
  for (let i=0; i<islands.length; i++) {
    const island = islands[i];
    Logs.insert('dark', '正在更新小岛: ' + island.Address);

    if (island.Status == 'unfollowed') {
      Logs.insert('dark', '自动忽略: ' + island.Name);
      continue;
    }

    const Hour = 60 * 60;
    if (dayjs().unix() - island.Checked < 24*Hour) {
      Logs.insert('info', `${island.Name} 距离上次更新时间未超过 24 小时，忽略本次更新。`);
      continue;
    }
    try {
      const status = await updateIsland(island.ID);
      if (status == 'alive') {
        Logs.insert('success', `${island.Name} 更新成功`);
      } else if (status == 'alive-but-no-news') {
        Logs.insert('success', `${island.Name} 连接成功，但没有新消息`);
      } else {
        Logs.insert('danger', `${island.Name} status: ${island.Status}`);
      }
    } catch (error) {
      Logs.insert('danger', `${island.Name} ${error}`);
    }
  }
  Logs.insert('primary', '操作结束，请手动刷新页面。');
}

function updateIsland(id) {
  return new Promise((resolve, reject) => {
    const timeout = window.setTimeout(() => {
      reject(Error('timeout'));
    }, 10*1000);

    const body = new FormData();
    body.set('id', id);
    ajax({method:'POST',url:'/api/update-island',body:body},
        // onSuccess
        (island) => {
          resolve(island.Status);
        }, (errMsg) => {
          // onError
          reject(errMsg);
        }, () => {
          // onAlways
          window.clearTimeout(timeout);
        });
  });
}

</script>
</body>
</html>